package net.yzxc.utils.controller;

import gnu.io.*;
import net.yzxc.utils.utils.SerialPortParameter;
import net.yzxc.utils.utils.SerialPortUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.server.PortInUseException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.TooManyListenersException;
import java.util.concurrent.ConcurrentHashMap;

@RestController
@RequestMapping("/rs232")
public class Rs232Controller {

    String weight = "";

    //用来存SerialPort对象。
    private static ConcurrentHashMap<String, SerialPort> serialPortMap = new ConcurrentHashMap<>();

    @Autowired
    private SerialPortUtil serialPortUtil;

    public static synchronized ConcurrentHashMap<String, SerialPort> getSerialPortMap() {
        return serialPortMap;
    }

    @RequestMapping("/getData")
    String getData() throws InterruptedException {
        List<String> postList = serialPortUtil.getSerialPortList();
        if(postList.isEmpty()){
            return "没找到串口信息!";
        }
        serialPortAction(postList.get(0));
        return weight;
    }

    /**
     * 连接串口
     *
     * @param name 串口名称
     */
    public void serialPortAction(String name) {
        //设置串口的listener
        try {
            CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(name);
            if(portIdentifier.isCurrentlyOwned()){
                sendData(serialPortMap.get(name));
                return;
            }
            SerialPortParameter serialPortParameter = new SerialPortParameter(name, 1200);
            final SerialPort serialPort = serialPortUtil.openSerialPort(serialPortParameter, 60);
            //保存串口对象
            serialPortMap.put(name, serialPort);
            sendData(serialPort);
            serialPortUtil.setListenerToSerialPort(serialPort, event -> {
                /**
                 * 总共有10类事件可以监听
                 * 此处只对两类事件进行了反应和处理
                 */
                switch (event.getEventType()) {
                    case SerialPortEvent.DATA_AVAILABLE: //接收到数据事件
                        try {
                            byte[] bytes = serialPortUtil.readData(serialPort);
                            if (bytes != null) {
                                // 将ASCII码数组转化为对应的字符串
                                String text = new String(bytes);
                                if (StringUtils.isNotBlank(text)) {
                                    // 去除不必要的字符
                                    text = text.replaceAll(" ", "");
                                    text = text.replaceAll("\r", "");
                                    text = text.replaceAll("\n", "");
                                    text = text.replaceAll("\t", "");
                                    weight = text;
//                                    System.out.println(name);
//                                    System.out.println("收到的数据长度：" + bytes.length);
//                                    System.out.println("重量为：" + text);
                                }
                            }
                        } catch (Exception e) {
                            System.out.println(e.toString());
                            // 发生读取错误时显示错误信息后退出系统
//                            System.exit(0);
                        } break;

                    case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2.输出缓冲区已清空
                        break;

                    case SerialPortEvent.CTS: // 3.清除待发送数据
                        break;

                    case SerialPortEvent.DSR: // 4.待发送数据准备好了
                        break;

                    case SerialPortEvent.RI: // 5.振铃指示
                        break;

                    case SerialPortEvent.CD: // 6.载波检测
                        break;

                    case SerialPortEvent.OE: // 7.溢位（溢出）错误
                        break;

                    case SerialPortEvent.PE: // 8.奇偶校验错误
                        break;

                    case SerialPortEvent.FE: // 9.帧错误
                        break;

                    case SerialPortEvent.BI: // 10.通讯中断
                        System.out.println("与串口设备通讯中断");
//                        System.exit(0);
                        serialPortAction(name);
                        break;

                    default:
                        break;
                }
            });
        } catch (TooManyListenersException | NoSuchPortException | UnsupportedCommOperationException e) {
            //不存在串口
            e.printStackTrace();
        } catch (PortInUseException e) {
            System.out.println("串口被占用");
            sendData(serialPortMap.get(name));
            e.printStackTrace();
        } catch (gnu.io.PortInUseException e) {
            System.out.println("串口被占用");
            sendData(serialPortMap.get(name));
//            throw new RuntimeException(e);
        }
    }

    /**
     * 关闭串口
     *
     * @param name 串口名称
     * @return
     */
    public String closeSerialPort(String name) {
        SerialPort serialPort = serialPortMap.get(name);
        serialPortUtil.closeSerialPort(serialPort);
        serialPortMap.remove(name);
        return "关闭串口";
    }

    public void sendData(SerialPort serialPort){
        byte[] byteArray = {'R'};
        serialPortUtil.sendData(serialPort, byteArray);
    }

}